package com.lyf.scm.admin.domain.service.impl;


import cn.hutool.core.date.DateException;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.github.pagehelper.PageInfo;
import com.lyf.scm.admin.api.dto.GmvTargetDTO;
import com.lyf.scm.admin.api.dto.GmvTargetInfoDTO;
import com.lyf.scm.admin.api.dto.PlanResponseDTO;
import com.lyf.scm.admin.domain.excel.dto.GmvTargetReadDTO;
import com.lyf.scm.admin.domain.remote.allocationservice.facade.GmvTargetFacade;
import com.lyf.scm.admin.domain.remote.basedata.dto.AreaDTO;
import com.lyf.scm.admin.domain.remote.basedata.dto.SaleOrgDTO;
import com.lyf.scm.admin.domain.remote.basedata.facade.BaseDataFacade;
import com.lyf.scm.admin.domain.remote.item.dto.CategoryBaseInfoDTO;
import com.lyf.scm.admin.domain.remote.item.facade.ItemCoreFacade;
import com.lyf.scm.admin.domain.service.GmvTargetService;
import com.lyf.scm.admin.domain.util.ExcelUtil;
import com.lyf.scm.common.constants.CommonConstants;
import com.lyf.scm.common.enums.ExcelExportTypeEnum;
import com.lyf.scm.common.enums.GmvImportTypeEnum;
import com.lyf.scm.common.enums.ResponseMsg;
import com.lyf.scm.common.model.ExcelExportDTO;
import com.lyf.scm.common.model.SalesPlanSelectDTO;
import com.lyf.scm.common.util.Snowflake;
import com.lyf.scm.common.util.date.MyDateUtil;
import com.rome.arch.core.exception.RomeException;
import com.rome.user.common.utils.UserContext;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * description:
 * gmv指标serviceImpl
 *
 * @author: haodong
 * @data: 2020/7/8 16:34
 */
@Slf4j
@Service
public class GmvTargetServiceImpl implements GmvTargetService {

    @Resource
    private GmvTargetFacade gmvTargetFacade;

    @Resource
    private ItemCoreFacade itemCoreFacade;

    @Resource
    private BaseDataFacade baseDataFacade;


    /**
     * 按条件查询gmv指标
     *
     * @param gmvTarget
     * @return
     */
    @Override
    public PlanResponseDTO<GmvTargetInfoDTO> listBySelective(GmvTargetDTO gmvTarget) {

        // List<SalesPlanSelectDTO> channelCodeList = baseDataFacade.getSubChannelCode(gmvTarget.getChannelCodeList());
        // List<SalesPlanSelectDTO> categoryCodeList = itemCoreFacade.getSubcategoryCode(gmvTarget.getCategoryCodeList());
        // List<SalesPlanSelectDTO> areaCodeList = baseDataFacade.getSubAreaCode(gmvTarget.getAreaCodeList());
        // BaseSearchUtil.setSearchFields(gmvTarget, channelCodeList, categoryCodeList, areaCodeList);

        if (!CollectionUtils.isEmpty(gmvTarget.getSaleOrgCodeList())) {
            gmvTarget.setSalesOrganizationList(gmvTarget.getSaleOrgCodeList().stream().map(SalesPlanSelectDTO::getCode).collect(Collectors.toList()));
        }

        Date endTime = gmvTarget.getEndTime();
        List<Map<String, Date>> monthDates;
        if (ObjectUtil.isNotNull(endTime)){
            monthDates = MyDateUtil.getMonthDates(gmvTarget.getStartTime(), endTime);
            gmvTarget.setStartTime(DateUtil.beginOfMonth(gmvTarget.getStartTime()));
            gmvTarget.setEndTime(DateUtil.endOfMonth(gmvTarget.getEndTime()));
            gmvTarget.setWeekDateList(monthDates);
        }else {
            // 默认14个月
            monthDates = MyDateUtil.getMonthDates(gmvTarget.getStartTime(), CommonConstants.MONTH_SIZE);
            gmvTarget.setStartTime(DateUtil.beginOfMonth(gmvTarget.getStartTime()));
            gmvTarget.setWeekDateList(monthDates);
            gmvTarget.setEndTime(MyDateUtil.getLastDate(null, monthDates));
        }
        PageInfo<GmvTargetInfoDTO> pageInfo = gmvTargetFacade.listBySelective(gmvTarget);
        PlanResponseDTO<GmvTargetInfoDTO> planResponse = new PlanResponseDTO<>();
        planResponse.setInfoList(pageInfo.getList());
        //格式化日期格式
        planResponse.setDateList(MyDateUtil.processDate(monthDates, "yyyy.MM"));
        planResponse.setTotal(pageInfo.getTotal());
        return planResponse;
    }

    /**
     * 查询全部gmv指标
     *
     * @param gmvTarget
     * @return
     */
    @Override
    public PlanResponseDTO<GmvTargetInfoDTO> listAllBySelective(GmvTargetDTO gmvTarget) {

        // List<SalesPlanSelectDTO> channelCodeList = baseDataFacade.getSubChannelCode(gmvTarget.getChannelCodeList());
        // List<SalesPlanSelectDTO> categoryCodeList = itemCoreFacade.getSubcategoryCode(gmvTarget.getCategoryCodeList());
        // List<SalesPlanSelectDTO> areaCodeList = baseDataFacade.getSubAreaCode(gmvTarget.getAreaCodeList());
        // BaseSearchUtil.setSearchFields(gmvTarget, channelCodeList, categoryCodeList, areaCodeList);

        Date startTime = DateUtil.beginOfMonth(gmvTarget.getStartTime());
        Date endTime = gmvTarget.getEndTime();
        List<Map<String, Date>> monthDates;

        if (null != endTime) {
            monthDates = MyDateUtil.getMonthDates(startTime, endTime);
            gmvTarget.setStartTime(startTime);
            gmvTarget.setEndTime(DateUtil.endOfMonth(gmvTarget.getEndTime()));
            gmvTarget.setWeekDateList(monthDates);
        } else {
            //没有结束时间，默认14个月
            monthDates = MyDateUtil.getMonthDates(startTime, CommonConstants.MONTH_SIZE);
            gmvTarget.setWeekDateList(monthDates);
            gmvTarget.setStartTime(startTime);
            gmvTarget.setEndTime(MyDateUtil.getLastDate(null, monthDates));
        }

        List<GmvTargetInfoDTO> targetInfoList = gmvTargetFacade.listAllBySelective(gmvTarget);
        PlanResponseDTO<GmvTargetInfoDTO> planResponse = new PlanResponseDTO<>();
        planResponse.setInfoList(targetInfoList);
        planResponse.setDateList(MyDateUtil.processDate(monthDates, "yyyy.MM"));
        return planResponse;
    }

    /**
     * 导入验证
     *
     * @param file Excel文件
     * @return
     */
    @Override
    public Boolean importVerification(MultipartFile file, Integer type) {
        List<GmvTargetReadDTO> gmvTargetReadList;
        try {
            gmvTargetReadList = ExcelUtil.readExcel(file.getInputStream(), GmvTargetReadDTO.class);
        } catch (IOException e) {
            throw new RomeException(ResponseMsg.EXCEPTION.getCode(), ResponseMsg.EXCEPTION.getMsg());
        }
        //获取导入数据中去重后的渠道code集合
        List<String> channelCodeList = gmvTargetReadList.stream().filter(item -> ObjectUtil.isNotNull(item.getChannelCode())).map(GmvTargetReadDTO::getChannelCode).distinct().collect(Collectors.toList());
        Boolean ifTrue;
        // 验证渠道code
        if (CollectionUtils.isNotEmpty(channelCodeList)) {
            // ifTrue = baseDataFacade.verificationChannelCode(channelCodeList);
            ifTrue = channelCodeList.containsAll(Arrays.asList("C0000"));
            if (!ifTrue) {
                throw new RomeException(ResponseMsg.PARAM_ERROR_2001.getCode(), ResponseMsg.PARAM_ERROR_2001.getMsg());
            }
        } else {
            throw new RomeException(ResponseMsg.PARAM_ERROR_2014.getCode(), ResponseMsg.PARAM_ERROR_2014.getMsg());
        }
        //获取导入数据中省份数据
        List<String> provinceList = gmvTargetReadList.stream().filter(item -> ObjectUtil.isNotNull(item.getProvince())).map(GmvTargetReadDTO::getProvince).distinct().collect(Collectors.toList());
        List<AreaDTO> areaList = new ArrayList<>();
        if (type.equals(GmvImportTypeEnum.TEMPLATE_DIR_FRA.getType())) {
            if (CollectionUtils.isNotEmpty(provinceList)) {
                // 获取省份信息
                areaList = baseDataFacade.listProvinceByList(provinceList);
                // 验证数据正确性
                ifTrue = areaList.size() == provinceList.size();
                if (!ifTrue || CollectionUtils.isEmpty(areaList)) {
                    throw new RomeException(ResponseMsg.PARAM_ERROR_2003.getCode(), ResponseMsg.PARAM_ERROR_2003.getMsg());
                }
            } else {
                throw new RomeException(ResponseMsg.PARAM_ERROR_2008.getCode(), ResponseMsg.PARAM_ERROR_2008.getMsg());
            }
        } else {
            if (CollectionUtils.isNotEmpty(provinceList)) {
                throw new RomeException(ResponseMsg.FAIL_2002.getCode(), ResponseMsg.FAIL_2002.getMsg());
            }
        }

        //获取导入数据中销售组织信息（子公司）数据
        List<String> salesOrgCodeList = gmvTargetReadList.stream().filter(item -> ObjectUtil.isNotNull(item.getSalesOrganizationCode())).map(GmvTargetReadDTO::getSalesOrganizationCode).distinct().collect(Collectors.toList());
        List<SaleOrgDTO> saleOrgList = new ArrayList<>();
        if (type.equals(GmvImportTypeEnum.TEMPLATE_DIR_FRA.getType())) {
            if (CollectionUtils.isNotEmpty(salesOrgCodeList)) {
                saleOrgList = baseDataFacade.verificationOrgCode(salesOrgCodeList);
                //验证销售组织Code
                ifTrue = saleOrgList.size() == salesOrgCodeList.size();
                if (!ifTrue || CollectionUtils.isEmpty(saleOrgList)) {
                    throw new RomeException(ResponseMsg.PARAM_ERROR_2002.getCode(), ResponseMsg.PARAM_ERROR_2002.getMsg());
                }
            } else {
                throw new RomeException(ResponseMsg.PARAM_ERROR_2030.getCode(), ResponseMsg.PARAM_ERROR_2030.getMsg());
            }
        }else {
            if (CollectionUtils.isNotEmpty(salesOrgCodeList)) {
                throw new RomeException(ResponseMsg.FAIL_2002.getCode(), ResponseMsg.FAIL_2002.getMsg());
            }
        }
        //获取导入数据中品类数据
        List<String> secCategory = gmvTargetReadList.stream().filter(item -> ObjectUtil.isNotNull(item.getSecCategory())).map(GmvTargetReadDTO::getSecCategory).distinct().collect(Collectors.toList());
        List<CategoryBaseInfoDTO> secCategoryList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(secCategory)) {
            //获取中分类数据
            secCategoryList = itemCoreFacade.listPriCategory(secCategory);
            // 验证数据正确性
            ifTrue = secCategoryList.size() == secCategory.size();
            if (!ifTrue || CollectionUtils.isEmpty(secCategoryList)) {
                throw new RomeException(ResponseMsg.PARAM_ERROR_2005.getCode(), ResponseMsg.PARAM_ERROR_2005.getMsg());
            }
        }
        List<GmvTargetDTO> gmvTargetList = this.getGmvTargetList(gmvTargetReadList, areaList, secCategoryList, saleOrgList);
        // todo 调取大数据获取实际gmv和实际毛利额
        gmvTargetList.forEach(gmv -> {
            double v = Math.random() * 100000000;
            gmv.setGmvRealTarget(new BigDecimal(String.valueOf(v)));
            double v1 = Math.random() * 200;
            gmv.setGrossProfitRealTarget(new BigDecimal(String.valueOf(v1)));
        });
        return gmvTargetFacade.batchSave(gmvTargetList);
    }

    /**
     * 导出Excel文件
     *
     * @param excelExportDTO
     * @param type
     */
    @Override
    public feign.Response exportExcel(ExcelExportDTO excelExportDTO, Integer type) {
        if (type == null) {
            throw new RomeException(ResponseMsg.FAIL_2005.getCode(), ResponseMsg.FAIL_2005.getMsg());
        }
        GmvTargetDTO gmvTargetDTO = new GmvTargetDTO();
        gmvTargetDTO.setChannelCodeList(excelExportDTO.getChannelCodeList());
        // gmvTargetDTO.setAreaCodeList(excelExportDTO.getAreaCodeList());
        gmvTargetDTO.setCategoryCodeList(excelExportDTO.getCategoryCodeList());
        // gmvTargetDTO.setSalesOrganizationList(excelExportDTO.getSaleOrgCodeList().stream().map(SalesPlanSelectDTO::getCode).distinct().collect(Collectors.toList()));//
        gmvTargetDTO.setAllChannelCode(excelExportDTO.getAllChannelCode());
        // 默认14个月
        List<Map<String, Date>> monthDates = MyDateUtil.getMonthDates(excelExportDTO.getStartTime(), CommonConstants.MONTH_SIZE);
        gmvTargetDTO.setStartTime(DateUtil.beginOfMonth(excelExportDTO.getStartTime()));
        gmvTargetDTO.setWeekDateList(monthDates);
        gmvTargetDTO.setEndTime(MyDateUtil.getLastDate(null, monthDates));
        gmvTargetDTO.setUnitType(excelExportDTO.getUnitType());
        //导出当页数据
        if (ExcelExportTypeEnum.CURRENT_PAGE_EXPORT.getType().equals(type)) {
            gmvTargetDTO.setPageNum(excelExportDTO.getPageNum());
            gmvTargetDTO.setPageSize(excelExportDTO.getPageSize());
        }
        //导出勾选
        if (ExcelExportTypeEnum.CHECKED_BOX_EXPORT.getType().equals(type)) {
            gmvTargetDTO.setPageNum(excelExportDTO.getPageNum());
            gmvTargetDTO.setPageSize(excelExportDTO.getPageSize());
            gmvTargetDTO.setRowIndex(excelExportDTO.getRowIndex());
        }
        //导出全部数据
        //获取三个查询条件的实际集合
        // List<SalesPlanSelectDTO> channelCodeList = baseDataFacade.getSubChannelCode(excelExportDTO.getChannelCodeList());
        // List<SalesPlanSelectDTO> categoryCodeList = itemCoreFacade.getSubcategoryCode(excelExportDTO.getCategoryCodeList());
        // List<SalesPlanSelectDTO> areaCodeList = baseDataFacade.getSubAreaCode(excelExportDTO.getAreaCodeList());
        // BaseSearchUtil.setSearchFields(gmvTargetDTO, channelCodeList, categoryCodeList, areaCodeList);
        return gmvTargetFacade.exportExcel(gmvTargetDTO, type);
    }

    /**
     * 更新销售额目标
     * @param gmvTarget
     * @return
     */
    @Override
    public Boolean updateTarget(List<GmvTargetDTO> gmvTarget) {
        if (CollectionUtils.isEmpty(gmvTarget)){
            throw new RomeException(ResponseMsg.PARAM_ERROR_2015.getCode(),ResponseMsg.PARAM_ERROR_2015.getMsg());
        }
        List<GmvTargetDTO> gmvTargetList = gmvTarget.stream().map(val -> {
            val.setModifier(UserContext.getUserId());
            val.setModifierName(UserContext.getUserId() == 0 ? "admin" : UserContext.getApplicationUser().getUsername());
            return val;
        }).collect(Collectors.toList());
        return gmvTargetFacade.updateTarget(gmvTargetList);
    }

    /**
     * 设置新增参数
     *
     * @param gmvTargetReadList Excel读取的数据集合
     * @param areaList          区域信息集合
     * @param secCategoryList   品类信息集合
     * @param saleOrgList       销售组织信息集合
     * @return
     */
    private List<GmvTargetDTO> getGmvTargetList(List<GmvTargetReadDTO> gmvTargetReadList, List<AreaDTO> areaList, List<CategoryBaseInfoDTO> secCategoryList, List<SaleOrgDTO> saleOrgList) {
        long sign = Snowflake.getInstanceSnowflake().nextId();
        ArrayList<GmvTargetReadDTO> paramList = gmvTargetReadList.stream().collect(Collectors.collectingAndThen(
                Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(
                        o -> o.getProvince() + o.getSalesOrganizationCode() +
                                o.getSecCategory() + o.getPlanDate()))), ArrayList::new));
        List<GmvTargetDTO> gmvTargetList = new ArrayList<>();
        paramList.forEach(item -> {
            GmvTargetDTO gmvTarget = new GmvTargetDTO();
            gmvTarget.setChannelCode(item.getChannelCode());
            gmvTarget.setChannelName(item.getChannelName());
            gmvTarget.setProvinceCode(areaList.stream().filter(area -> area.getName().equals(item.getProvince())).map(AreaDTO::getCode).collect(Collectors.joining()));
            gmvTarget.setProvinceName(areaList.stream().filter(area -> area.getName().equals(item.getProvince())).map(AreaDTO::getName).collect(Collectors.joining()));
            gmvTarget.setSalesOrganizationCode(saleOrgList.stream().filter(org -> org.getOrgCode().equals(item.getSalesOrganizationCode())).map(SaleOrgDTO::getOrgCode).collect(Collectors.joining()));
            gmvTarget.setSalesOrganizationName(saleOrgList.stream().filter(org -> org.getOrgCode().equals(item.getSalesOrganizationCode())).map(SaleOrgDTO::getOrgName).collect(Collectors.joining()));
            gmvTarget.setPriCategoryCode(secCategoryList.stream().filter(category -> String.valueOf(category.getCode()).equals(item.getSecCategory())).findFirst().get().getCode().toString());
            gmvTarget.setPriCategoryName(secCategoryList.stream().filter(category -> String.valueOf(category.getCode()).equals(item.getSecCategory())).findFirst().get().getName());
            // gmvTarget.setSecCategoryCode(item.getSecCategory());
            // gmvTarget.setSecCategoryName(item.getSecCategory());
            try {
                try {
                    gmvTarget.setPlanStartDate(DateUtil.beginOfMonth(DateUtil.parse(item.getPlanDate(),"yyyy/MM")));
                    gmvTarget.setPlanEndDate(DateUtil.beginOfDay(DateUtil.endOfMonth(DateUtil.parse(item.getPlanDate(),"yyyy/MM"))));
                } catch (DateException e) {
                    gmvTarget.setPlanStartDate(DateUtil.beginOfMonth(DateUtil.parseDate(item.getPlanDate())));
                    gmvTarget.setPlanEndDate(DateUtil.beginOfDay(DateUtil.endOfMonth(DateUtil.parseDate(item.getPlanDate()))));
                }
            } catch (DateException e) {
                throw new RomeException(ResponseMsg.PARAM_ERROR_2031.getCode(),ResponseMsg.PARAM_ERROR_2031.getMsg());
            }
            gmvTarget.setCreator(UserContext.getUserId());
            gmvTarget.setCreatorName(UserContext.getUserId() == 0 ? "admin" : UserContext.getApplicationUser().getUsername());
            gmvTarget.setModifierName(UserContext.getUserId() == 0 ? "admin" : UserContext.getApplicationUser().getUsername());
            gmvTarget.setGmvOriginalTarget(new BigDecimal(item.getGmvTarget()));
            gmvTarget.setGmvTarget(new BigDecimal(item.getGmvTarget()));
            gmvTarget.setGrossProfitTarget(new BigDecimal(item.getGrossProfitTarget()));
            gmvTarget.setOpSign(String.valueOf(sign));
            gmvTargetList.add(gmvTarget);
        });
        return gmvTargetList.stream().collect(Collectors.collectingAndThen(
                        Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(
                                                o -> o.getProvinceCode() + o.getSalesOrganizationCode() +
                                                        o.getPriCategoryCode() + o.getPlanStartDate()))), ArrayList::new));
    }

}